//
// Created by tcj on 2022/7/12.
//

#include "buffer.h"
#include "assert.h"
namespace tcj{
    Buffer::Buffer(int initBufferSize):buffer_(initBufferSize),readPos_(0),writePos_(0) {
    }

    //缓存区中可以读取的字节数
    ssize_t Buffer::readableBytes() const {
        return writePos_ - readPos_;
    }
    //缓存区中可以写入的字节数
    ssize_t Buffer::writeableBytes() const {
        return buffer_.size() - writePos_;
    }
    //缓存区中已经读取的字节数
    size_t Buffer::readBytes() const {
        return readPos_;
    }

    const char *Buffer::curReadPtr() const {
        return BeginPtr_()+readPos_;
    }

    //获取当前读指针
    const char *Buffer::curWritePtrconst() const {
        return BeginPtr_()+writePos_;
    }

    //获取当前写指针
    char *Buffer::curWritePtr() {
        return BeginPtr_()+writePos_;
    }

    //更新读指针
    void Buffer::updateReadPtr(size_t len){
        assert(len <= readableBytes());
        readPos_ += len;
    }

    // 将读指针更新到哪
    void Buffer::updateReadPtrUntilEnd(const char *end) {
        assert(end>=curReadPtr());
        updateReadPtr(end-curReadPtr());
    }

    //更新写指针
    void Buffer::updateWritePtr(size_t len) {
        assert(len<=writeableBytes());
        writePos_+=len;
    }

    //将读指针和写指针初始化
    void Buffer::initPtr() {
        // 置字节字符串s的前n个字节为零且包括‘\0’。　　
        bzero(&buffer_[0],buffer_.size());
        readPos_=0;
        writePos_=0;
    }

    //用于缓冲区空间不够时的扩容
    void Buffer::allocateSpace(size_t len) {
        //如果buffer_里面剩余的空间有len就进行调整，否则需要申请空间。
        //剩余空间包括write指针之前的空间和可写的空间
        if(writeableBytes()+readBytes()<len)
        {
            buffer_.resize(writePos_+len+1);
        }
        else{
            //将读指针置为0,调整一下
            size_t readable=readableBytes();
            std::copy(BeginPtr_()+readPos_,BeginPtr_()+writePos_,BeginPtr_());
            readPos_=0;
            writePos_=readable;
            assert(readable==readableBytes());
        }
    }

    //保证将数据写入缓冲区
    void Buffer::ensureWriteable(size_t len) {
        if(writeableBytes()<len)
        {
            allocateSpace(len);
        }
        assert(writeableBytes()>=len);
    }

    //将数据写入到缓冲区
    void Buffer::append(const char* str,size_t len)
    {
        assert(str);
        ensureWriteable(len);
        std::copy(str,str+len,curWritePtr());
        updateWritePtr(len);
    }

    void Buffer::append(const std::string& str)
    {
        append(str.data(),str.length());
    }

    void Buffer::append(const void* data,size_t len)
    {
        assert(data);
        append(static_cast<const char*>(data),len);
    }

    void Buffer::append(const Buffer& buffer)
    {
        append(buffer.curReadPtr(),buffer.readableBytes());
    }

    //IO操作的读与写接口
    ssize_t Buffer::ReadFd(int fd,int* Errno)
    {
        char buff[65535];//暂时的缓冲区
        struct iovec iov[2];
        /*
        struct iovec {
            ptr_t iov_base;  Starting address
            size_t iov_len;  Length in bytes
        }
         *
         * */
        const size_t writable=writeableBytes();
        cout<<"writable is "<<writable<<endl;
        iov[0].iov_base=BeginPtr_()+writePos_;
        iov[0].iov_len=writable;
        iov[1].iov_base=buff;
        iov[1].iov_len=sizeof(buff);

        /**/
        const ssize_t len=readv(fd,iov,2);
        cout<<"len is "<<len<<endl;
        if(len<0)
        {
            //std::cout<<"从fd读取数据失败！"<<std::endl;
            *Errno=errno;
        }
        else if(static_cast<size_t>(len)<=writable)
        {
            writePos_+=len;
        }
        else{
            writePos_=buffer_.size();
            append(buff,len-writable);
        }
        return len;
    }

    ssize_t Buffer::WriteFd(int fd,int* Errno)
    {
        size_t readSize=readableBytes();
        ssize_t len=write(fd,curReadPtr(),readSize);
        if(len<0)
        {
            //std::cout<<"往fd写入数据失败！"<<std::endl;
            *Errno=errno;
            return len;
        }
        readPos_+=len;
        return len;
    }

    //将缓冲区的数据转化为字符串
    std::string Buffer::AlltoStr()
    {
        std::string str(curReadPtr(),readableBytes());
        initPtr();
        return str;
    }

    //返回指向缓冲区初始位置的指针
    char* Buffer::BeginPtr_()
    {
        return &*buffer_.begin();
    }

    const char* Buffer::BeginPtr_() const
    {
        return &*buffer_.begin();
    }


}